package com.example.shirotest.console;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.example.shirotest.entry.HtmlRegex;
import com.example.shirotest.entry.Result;
import com.example.shirotest.entry.Sites;
import com.example.shirotest.mapper.ResultMapper;
import com.example.shirotest.mapper.SitesMapper;
import com.example.shirotest.service.ResultService;
import com.example.shirotest.service.SitesService;
import com.example.shirotest.utils.HtmlParse;
import com.example.shirotest.utils.ToolUtil;
import com.google.gson.Gson;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.UncategorizedSQLException;
import org.springframework.stereotype.Component;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.concurrent.ArrayBlockingQueue;

@Component
public class GetRemoteData {

    @Autowired
    private SitesMapper sitesMapper;

    @Autowired
    private ResultMapper resultMapper;

    @Autowired
    private ResultService resultService;

    @Autowired
    private SitesService sitesService;

    @Autowired
    private Gson gson;
    
    //资源的开始id
    private Integer startId = 0;
    //本轮是否结束
    private boolean isEnd = false;
    //是否正则执行
    private boolean isRuning = false;

    //保存已存在的链接，每个数据源最近100条数据
    private HashMap<Integer, HashSet<String>> UniqueMap = new HashMap<>();

    //加载的数据源
    private ArrayBlockingQueue<Sites> shareData = new ArrayBlockingQueue<>(10);

    public boolean getIsEnd(){
        return isEnd;
    }

    public void setEnd(boolean isEnd){
        this.isEnd = isEnd;
    }

    public Integer getStartId(){
        return startId;
    }

    public void setStartId(Integer startId){
        this.startId = startId;
    }

    public HashMap getUniqueMap(){
        return UniqueMap;
    }

    public boolean getIsRuning(){
        return isRuning;
    }

    public void setIsRuning(boolean isRuning){
        this.isRuning = isRuning;
    }

    public void start(){
        if(this.isRuning)return;
        this.isRuning = true;
        this.isEnd = false;
    }

    /**
     * 加载数据源最新的100条数据，用于去重判断
     * @param sid  数据源id
     */
    public void loadUnique(Integer sid){
        HashSet<String> set = UniqueMap.get(sid);
        if(set==null){
            ArrayList<Result> list = resultMapper.selectBySid(sid);
            System.out.println(ToolUtil.getCurDateTimeStr() + "site-" + sid+" : loadUnique ");
            set = new HashSet<String>();
            if(list.size()>0){
                for (Result vo : list) {
                    set.add(vo.getUrl());
                }
            }else{
                //如果查无数据，则设置一个开始值，避免重复查询数据库
                set.add("init-start");
            }

            UniqueMap.put(sid,set);
        }
    }

    //清空去重缓存
    public void clearUniqueMap(){
        UniqueMap.clear();
    }


    /**
     * 判断当前数据是否是唯一的 true-唯一  false-不是唯一
     * @param sid 数据源id
     * @param url 链接地址
     * @return
     */
    public boolean isUnique(Integer sid,String url){
        HashSet<String> set = UniqueMap.get(sid);
        if(null==set){
            //加载数据
            loadUnique(sid);
        }

        set = UniqueMap.get(sid);

        if(set.contains(url)){
            return false;
        }

        //把数据加入
        set.add(url);
        UniqueMap.put(sid,set);

        return true;
    }

    //加载站点资源
    public void loadSite(){
        if(shareData.size() > 0){
            return;
        }

        QueryWrapper<Sites> wrapper = new QueryWrapper<Sites>();
        wrapper.gt("id",startId);
        wrapper.eq("state",1);
        wrapper.last("limit 10");
        List<Sites> list = sitesMapper.selectList(wrapper);

        if(list.size()==0){
            isEnd = true;
            isRuning = false;
            return;
        }

        for (Sites sites : list) {
            startId = sites.getId();
            shareData.add(sites);
        }

    }

    //获取数据
    public ArrayBlockingQueue<Sites> getData(){
        return shareData;
    }


    //抓取并保存数据
    public void getHref(Sites sites){
        String urllink = sites.getUrl();
        String regex   = sites.getRegex();

        HtmlRegex htmlRegex = gson.fromJson(regex, HtmlRegex.class);

        ArrayList<Result> results = null;
        try {
            results = HtmlParse.getNetContent(urllink, htmlRegex);
        } catch (IOException e) {
            sitesService.emptyCount(sites.getId(),"内容解析异常");
            System.out.println(ToolUtil.getCurDateTimeStr() + Thread.currentThread().getName() + " warn: GetHref IOException, " + e.getMessage());
            return;
        }

        if(results==null || results.size()==0){
            sitesService.emptyCount(sites.getId(),"未获取到数据");
            System.out.println(ToolUtil.getCurDateTimeStr() + Thread.currentThread().getName() + " warn: Get Nothing");
            return;
        }

        //数据判断去重
        ArrayList<Result> res = new ArrayList<>();
        for (Result result : results) {
            if(isUnique(sites.getId(),result.getUrl())){
                result.setSid(sites.getId());
                res.add(result);
            }
        }

        if(res==null || res.size()==0){
            sitesService.emptyCount(sites.getId(),"最近没有更新，去重前数据："+results.size());
            System.out.println(ToolUtil.getCurDateTimeStr() + Thread.currentThread().getName() + " say: 0 append");
            return;
        }

        try {
            resultService.saveBatch(res);
        }catch (UncategorizedSQLException e){
            sitesService.emptyCount(sites.getId(),"批量添加异常");
            System.out.println(ToolUtil.getCurDateTimeStr() + Thread.currentThread().getName() + " say: " + e.getMessage());
            return;
        }

        sitesService.updatetime(sites.getId(),res.size());

        System.out.println(ToolUtil.getCurDateTimeStr() + Thread.currentThread().getName() + " say: " + res.size() + " append");
    }

}
